
import 'dart:convert';

import 'package:im_app/im/util/MapUtil.dart';
import 'package:logger/logger.dart';
import 'package:sqflite/sqflite.dart';

import '../util/DateUtil.dart';
import '../util/ImSingleton.dart';
import '../pojo/ImPojo.dart';
import 'BaseDao.dart';

class ImMessageSendDao extends BaseDao {

  final _logger = Logger(
    printer: PrettyPrinter(),
  );

  Future<List<ImMessageSend>> getByMessageId(int messageId) async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    String sql = "select * from im_message_send where messageId = ?";
    List<Map<String, Object?>>? list = await database?.rawQuery(sql, [messageId]);
    return list != null ? list.map((map)=>_toImMessageSend(map)).toList() : [];
  }

  Future<ImMessageSend?> getByMessageIdAndUserId(int messageId, String userId) async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    String sql = "select * from im_message_send where messageId = ? and userId = ?";
    List<Map<String, Object?>>? list = await database?.rawQuery(sql, [messageId, userId]);
    if (list != null && list.length > 0) {
      return Future.value(_toImMessageSend(list[0]));
    }
    return null;
  }

  Future<void> batchInserts(List<ImMessageSend> messageSendList) async {
    if (messageSendList.isEmpty) return;
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    Batch? batch = database?.batch();
    for (var messageSend in messageSendList) {
      var data = _toInsertValueMap(messageSend);
      batch?.insert("im_message_send", data);
    }
    List<Object?>? list = await batch?.commit();
    _logger.i("batch insert message send json: ${list?.length}");
  }

  Future<void> batchInserts2(List<ImMessage> messageList) async {
    if (messageList.isEmpty) return;
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    Batch? batch = database?.batch();
    for (var message in messageList) {
      var messageSendList = message.messageSendSet;
      if (messageSendList != null) {
        for (var messageSend in messageSendList) {
          messageSend.messageId = message.id;
          var data = _toInsertValueMap(messageSend);
          batch?.insert("im_message_send", data);
        }
      }
    }
    List<Object?>? list = await batch?.commit();
    _logger.i("batch insert message send json: ${list?.length}");
  }

  Future<void> batchUpdates(List<ImMessageSend> messageSendList) async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    Batch? batch = database?.batch();
    for (var messageSend in messageSendList) {
      var data = _toUpdateValueMap(messageSend);

      batch?.update("im_message_send", data, where: "id=?",
          whereArgs:[messageSend.id]);
    }
    List<Object?>? list = await batch?.commit();
    _logger.i('batch updateMessages json: ${jsonEncode(list)}');
  }

  Future<void> batchChangeMessageSendActionStatus(String userId, List<ImMessageSend> messageSends) async {
    if (messageSends.isEmpty) return;
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    Batch? batch = database?.batch();
    for (var messageSend in messageSends) {
      batch?.rawUpdate("update im_message_send set actionStatus = ?, updateTime=? where id = ?",
        [messageSend.actionStatus?.value, DateUtil.formatDate(messageSend.updateTime),  messageSend.id]);
    }
    List<Object?>? list = await batch?.commit();
    _logger.i("batch update message send json: ${list?.length}");
  }

  Future<void> cleanMessageSends(List<int> messageIds) async {
    if (messageIds.isEmpty) return;
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    Batch? batch = database?.batch();
    for (var messageId in messageIds) {
      batch?.delete("im_message_send", where: "messageId = ?",  whereArgs: [messageId]);
    }
    List<Object?>? list = await batch?.commit();
    _logger.i("db clean message send json: ${list?.length}");
  }

  Map<String, Object?> _toInsertValueMap(ImMessageSend messageSend) {
    Map<String, Object?> map = {};
    map['messageId'] = messageSend.messageId;
    map['userId'] = messageSend.userId;
    map['status'] = messageSend.status.value;
    map['fileStatus'] = messageSend.fileStatus?.value;
    map['actionStatus'] = messageSend.actionStatus?.value;
    map['createTime'] = DateUtil.formatDate(messageSend.createTime);
    map['updateTime'] = DateUtil.formatDate(messageSend.updateTime);

    return map;
  }

  Map<String, Object?> _toUpdateValueMap(ImMessageSend messageSend) {
    Map<String, Object?> map = {};
    map['actionStatus'] = messageSend.actionStatus?.value;
    map['updateTime'] = DateUtil.formatDate(messageSend.updateTime);

    return map;
  }

  ImMessageSend _toImMessageSend(Map<String, Object?> map) {
    var messageSend = ImMessageSend(userId: MapUtil.getString(map, "userId"), status: ImMessageStatus.ofValue(MapUtil.getInt(map, "status")));
    messageSend.fileStatus = ImMessageFileStatus.ofValue(MapUtil.getIntOrNull(map, "fileStatus"));
    messageSend.actionStatus = ImMessageActionStatus.ofValue(MapUtil.getIntOrNull(map, "actionStatus"));
    messageSend.createTime = MapUtil.getDate(map, "createTime");
    messageSend.updateTime = MapUtil.getDate(map, "updateTime");
    return messageSend;
  }
}